//兼容不同版本的分隔符，如\r\n、\n、\r，使服务器能够按行读取客户端发来的请求报文的信息
#pragma once
#include<iostream>
#include<string>
#include<sys/types.h>
#include<sys/socket.h>
//工具类
class Util
{
    public:

        //把一大串（其中含有分隔符的）字符串按行读取（分割），out是输出型参数
        static int ReadLine(int sock,std::string &out)
        {
            char ch='X';
            while(ch!='\n')//读取到不是\n就进入该循环逻辑
            {
                ssize_t s=recv(sock,&ch,1,0);//从套接字中读取数据
                if(s>0)//读取成功
                {
                    //读取到\r后才需做额外的特殊处理，\r转成\n 或者 \r\n转成\n
                    if(ch=='\r')
                    {
                        recv(sock,&ch,1,MSG_PEEK);//设置MSG_PEEK选项，数据窥探，只读取数据而不从缓冲区中把数据拿走

                        //窥探\r后面的字符是否依旧是分隔符\n，还是正常的字符ABcd
                        if(ch=='\n')//窥探成功，证明\r后面的字符是\n，证明客户端发来的请求分隔符版本是\r\n
                        {
                            recv(sock,&ch,1,0);//可以把以\n结尾的数据从接收缓冲区中拿取了，（缓冲区的数据拿取后被清除）
                        }
                        //else 说明\r下一个字符不是分隔符\n，而是代表正文数据的字符，也说明客户端发来的请求的分隔符版本只是简单的\r，后面没有\n
                        else
                        {
                            ch = '\n';//把结尾的\r分隔符同一转换为\n
                        }
                    }
                    //普通字符或\n字符就Push进out参数里
                    out.push_back(ch);
                }
                else if(s==0)//连接关闭了
                {
                    return 0;
                }
                else//读取失败 
                {
                    return -1;
                }
            }
            return out.size();//返回读取的长度
        }
        //以sep作为分隔符切割字符串
        static bool CutString(const std::string &target,std::string &sub1_out,
            std::string &sub2_out,std::string sep)
        {
            size_t pos = target.find(sep);
            if(pos!= std::string::npos)
            {
                sub1_out = target.substr(0,pos);//左闭右开
                sub2_out = target.substr(pos+sep.size());//从下一个不是分隔符的字符开始截取
                return true;
            }
            return false;
        }
};